#ifndef SHM_HPP

#define SHM_HPP

#include <iostream>
#include <stdio.h>
#include <string>
#include <cstdio>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <unistd.h>

#define PATH "."

#define USER "user"
#define CREATER "creater"

const int prev = -1;
const int proj = 0x66;

#define ERR_SIGNAL 1

#define ERR_EXIT(m) \
do                  \
{                   \
    perror(m);      \
    exit(ERR_SIGNAL);\
}while(0)

const int gmode = 0666;


// 管理共享内存，

class Shm
{
public:
    Shm(const char* path,int shmid ,int proj_id,int size,const char* s)
        :_path(path)
        ,_shmid(shmid)
        ,_proj_id(proj_id)
        ,_size(size)
        ,_mem(nullptr)
        ,_usertype(s)
    {
        _key = ftok(path,proj_id);

        if(_key == -1)
        {
            ERR_EXIT("key");
        }
    }

    ~Shm()
    {
        shmdt(_mem);
        if(_usertype == CREATER)
        {
            Destroy();
        }
    }

    // 创建共享内存
    //void Create(const char* path,int proj_id,int size)
    void Create()
    {
        // key_t k = ftok(_path.c_str(),_proj_id);

        // if(k < 0)
        // {
        //     ERR_EXIT("ftok");
        // }

        //_size = size;

        _shmid = shmget(_key,_size,IPC_CREAT | IPC_EXCL | gmode);

        if(_shmid < 0)
        {
            ERR_EXIT("shm create");;
        }

        _mem = (char*)shmat(_shmid,nullptr,0);
    }

    //void Get(const char* path,int proj_id,int size)
    void Get()
    {
        // key_t k = ftok(path,proj_id);

        // if(k < 0)
        // {
        //     ERR_EXIT("ftok");
        // }

        _shmid = shmget(_key,_size,IPC_CREAT | gmode);

        if(_shmid < 0)
        {
            ERR_EXIT("shm get");;
        }

        _mem = (char*)shmat(_shmid,nullptr,0);
    }

    char* VitualPtr()
    {
        std::cout << (void*)_mem << std::endl;
        return _mem;
    }

    void Destroy()
    {
        shmctl(_shmid, IPC_RMID, nullptr);
    }

    // void Write(const char* s)
    // {
    //     for(int i = 0;s[i];++i)
    //     {
    //         if(i == _size - 1)
    //         {
    //             _mem[_size - 1] = 0;
    //             return ;
    //         }
    //         _mem[i] = s[i];
    //     }

    //     _mem[_size - 1] = 0;
    // }

    // void Write(const std::string& s)
    // {
    //     for(int i = 0;i < s.size();++i)
    //     {
    //         if(i == _size - 1)
    //         {
    //             _mem[_size - 1] = 0;
    //             return ;
    //         }
    //         _mem[i] = s[i];
    //     }

    //     _mem[s.size()] = 0;
    // }

    // void Read()
    // {
    //     std::cout << _mem << std::endl;
    // }
private:
    std::string _path;
    int _proj_id;
    int _key;
    int _shmid;
    int _size;
    char* _mem;
    std::string _usertype;
};

#endif